import java.awt.Color;
import java.util.ArrayList;

import uchicago.src.sim.gui.Drawable;
import uchicago.src.sim.gui.SimGraphics;
import uchicago.src.sim.space.Object2DTorus;

public class Commander implements Drawable {
	
	// enums
    public enum Positioning { front, back, mixed };
    public enum Intelligence { near, recent };

    // constants
	private static final Color commanderColor = Color.WHITE;
	
    // variables
    private Point p;
    private Color color;
    private Object2DTorus space;
    private Positioning positioning;
    private Intelligence intelligence;
    private String sWind;
    private int nFirefighters;
    
    public Commander(Point p, int positioning, int intelligence, Object2DTorus space, String sWind, int nFirefighters) {
        this.p = p;
        this.color = commanderColor;
        this.space = space;
        this.sWind = sWind;
        this.nFirefighters = nFirefighters;        
        this.positioning = getPositioning(positioning);
        this.intelligence = getIntelligence(intelligence);
    }
    
    public Intelligence getIntelligence(int n) {
    	if (n == 1) return Intelligence.near;
    	else if (n == 2) return Intelligence.recent;
    	else return null;
    }
    
    public Positioning getPositioning(int n) {
    	if (n == 1) return Positioning.front;
    	else if (n == 2) return Positioning.back;
    	else if (n == 3) return Positioning.mixed;
    	return null;
    }
    
    public void firstAction(Firefighter f, int i) {    	
    	
    	Point origin = getFireOrigin();
    	int radius = getFireRadius(origin);

		if (f.isFirebreaker()) {
			f.setGoTo(f.getFrontFirePoint(origin, radius, 0, 5, sWind, radius));
			f.setFirebreakPointI(f.getFrontFirePoint(origin, radius, 0, 5, sWind, radius));
			f.setFirebreakPointF(f.getFrontFirePoint(origin, radius, 4, 5, sWind, radius));
		}

		else  if (positioning == Positioning.front) {
			f.setGoTo(f.getFrontFirePoint(origin, radius, i, nFirefighters, sWind, radius));
		}
		
		else if (positioning == Positioning.back) {
			f.setGoTo(f.getBackFirePoint(origin, radius, i, nFirefighters, sWind));
		}
		
		else if (positioning == Positioning.mixed) {
			f.setGoTo(f.getMixedPoint(origin, radius, i, nFirefighters, sWind, radius));
		}
    }
    
    public ArrayList<Cell> getBurningCells() {
        ArrayList<Cell> ret = new ArrayList<Cell>();
        for (int x = 0; x < space.getSizeX(); x++)
        	for (int y = 0; y < space.getSizeY(); y++) {
        		Cell c = (Cell) space.getObjectAt(x, y);
        		if (c.isBurning())
                    ret.add(c);
        	}        		
        return ret;
    }

    public ArrayList<Cell> getBurntCells() {
        ArrayList<Cell> ret = new ArrayList<Cell>();
        for (int x = 0; x < space.getSizeX(); x++)
        	for (int y = 0; y < space.getSizeY(); y++) {
        		Cell c = (Cell) space.getObjectAt(x, y);
        		if (c.isBurnt())
        			ret.add(c);
        	}
        return ret;
    }

    public void action(Firefighter firefighter) {
		
		if (firefighter.isIdle()) {
			
			if (intelligence == Intelligence.near) {
				Point p = getNearCell(firefighter);
				if (p != null) firefighter.setGoTo(p);			
			}
			
			else if (intelligence == Intelligence.recent) {
				Point p = getRecentCell(firefighter);
				if (p != null) firefighter.setGoTo(p);
			}
		}
    }
    
    public Point getRecentCell(Firefighter f) {
    	Point ret = null;
    	int min = Integer.MAX_VALUE;
    	for (int x = 0; x < space.getSizeX(); x++)
    		for (int y = 0; y < space.getSizeY(); y++) {
    			Cell c = (Cell) space.getObjectAt(x, y);
    			if (c.isBurning() && c.getFireTicks() < min) {
    				min = c.getFireTicks();
    				ret  = new Point(x,y);
    			}
    		}
    	return ret;    			
    }

    @Override
    public void draw(SimGraphics g) {
        g.drawFastCircle(color);
    }

    public Color getColor() {
        return color;
    }

    public int getDistance(Point src, Point dest) {    	
 		int dx = Math.abs(src.x - dest.x);    	
 		int dy = Math.abs(src.y - dest.y);
 		
 		if (Math.max(dx, dy) == dx) 
 			return dy + (dx-dy);
 		else
 			return dx + (dy-dx);
 	}
    
    public Point getFireOrigin() {
    	for (int x = 0; x < space.getSizeX(); x++)
    		for (int y = 0; y < space.getSizeY(); y++) {
    			Cell c = (Cell) space.getObjectAt(x, y);
    			if (c.isBurning())
    				return c.getPoint();
    		}
    	return null;    			
    }
    
    public int getFireRadius(Point dest) {
 		return getDistance(new Point(0,0), dest) / 2;		
 	}
 	
 	public Point getNearCell(Firefighter firefighter) {
 		
 		ArrayList<Cell> burningCells = getBurningCells(); 		
		Point ret = null;
		int min = Integer.MAX_VALUE;
		for (Cell c : burningCells) {
			int d = getDistance(firefighter.getPoint(), c.getPoint());
			if (d < min) {
				min = d;
				ret = c.getPoint();
			}
		}
		return ret; 
	}

	@Override
    public int getX() {
        return p.x;
    }
	
	@Override
    public int getY() {
        return p.y;
    }
	
	public boolean noMoreFire() {
		for (int x = 0; x < space.getSizeX(); x++)
			for (int y = 0; y < space.getSizeY(); y++) {
				Cell c = (Cell) space.getObjectAt(x, y);
				if (c.isBurning())
					return false;
			}
		return true;
	}
	
}
